﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Wazzup.Engine.Constants;
using Wazzup.Engine.Utility;


namespace Wazzup.Engine.Requests
{
    public static class WhatsRegisterV2
    {
        public static string GenerateIdentity(string phoneNumber, string salt = "")
        {
            return Reverse((phoneNumber + salt)).ToShaString();
        }

        public static string GetToken(string number)
        {
            return WhatsToken.GenerateToken(number);
        }

        /// <summary>
        /// Requesting WhatsApp Registration Code
        /// </summary>
        /// <param name="countryCode"></param>
        /// <param name="phoneNumber"></param>
        /// <param name="method"></param>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="locale"></param>
        /// <param name="mcc"></param>
        /// <param name="salt"></param>
        /// <returns></returns>
        public static async Task<string> RequestCode(string countryCode, string phoneNumber, string method = "sms", string id = null, string language = null, string locale = null, string mcc = "204", string salt = "")
        {
            try
            {
                if (string.IsNullOrEmpty(language) || string.IsNullOrEmpty(locale))
                {
                    CultureInfo.CurrentCulture.GetLanguageAndLocale(out language, out locale);
                }
                if (string.IsNullOrEmpty(id))
                {
                    //auto-generate
                    id = GenerateIdentity(phoneNumber, salt);
                }
                var token = GetToken(phoneNumber);
                //string.Concat(WhatsAppConstant.WhatsRegToken + WhatsAppConstant.WhatsBuildHash, phoneNumber).ToMD5String();
                var uri = string.Format("https://v.whatsapp.net/v2/code?cc={0}&in={1}&to={0}{1}&lg={2}&lc={3}&mcc={7}&mnc=008&method={4}&id={5}&token={6}", countryCode, phoneNumber, language, locale, method, id, token, mcc);
                var response = await GetResponse(uri);
                var password = response.GetJsonValue("pw");
                return !string.IsNullOrEmpty(password) ? password : "";
            }
            catch
            {
                return "";
            }
        }
        /// <summary>
        /// Register the Code which got from Request Code
        /// </summary>
        /// <param name="countryCode"></param>
        /// <param name="phoneNumber"></param>
        /// <param name="code">This Code got from the SMS / Voice Verification</param>
        /// <param name="id"></param>
        /// <param name="salt"></param>
        /// <returns></returns>
        public static async Task<string> RegisterCode(string countryCode, string phoneNumber, string code, string id = null, string salt = "")
        {
            try
            {
                if (string.IsNullOrEmpty(id))
                {
                    //auto generate
                    id = GenerateIdentity(phoneNumber, salt);
                }
                var uri = string.Format("https://v.whatsapp.net/v2/register?cc={0}&in={1}&id={2}&code={3}", countryCode, phoneNumber, id, code);
                var response = await GetResponse(uri);
                return response.GetJsonValue("status") == "ok" ? response.GetJsonValue("pw") : "";
            }
            catch
            {
                return "";
            }
        }

        public static string Reverse(string text)
        {
            var cArray = text.ToCharArray();
            var reverse = String.Empty;
            for (var i = cArray.Length - 1; i > -1; i--)
            {
                reverse += cArray[i];
            }
            return reverse;
        }

        public static async Task<string> RequestExist(string countryCode, string phoneNumber, string id = null)
        {
            try
            {
                if (String.IsNullOrEmpty(id))
                {
                    id = Reverse(phoneNumber).ToShaString();
                }
                var uri = string.Format("https://v.whatsapp.net/v2/exist?cc={0}&in={1}&id={2}", countryCode, phoneNumber, id);
                var response = await GetResponse(uri);
                return response.GetJsonValue("status") == "ok" ? response.GetJsonValue("pw") : null;
            }
            catch
            {
                return null;
            }
        }

        private static async Task<string> GetResponse(string uri)
        {
            var httpClient = new HttpClient();
            var url = new Uri(uri);
            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);
            httpRequestMessage.Headers.Add("User-Agent", WhatsAppConstant.UserAgent);
            var response = await httpClient.SendAsync(httpRequestMessage);
            response.EnsureSuccessStatusCode();
            var res = await response.Content.ReadAsStringAsync();
#if DEBUG
            var sb = new StringBuilder();
            sb.AppendLine("Url : " + uri);
            sb.AppendLine("Result : " + res);
            System.Diagnostics.Debug.WriteLine(string.Format("Request to Whatsapp Web Service Log : {0}{1}", Environment.NewLine, sb));
#endif

            return res;
        }

        private static string ToShaString(this IEnumerable<char> s)
        {
            return new string(s.ToArray()).ToShaString();
        }

        private static string ToShaString(this string s)
        {
            var data = EncryptionHelper.EncryptSha1(s);
            var str = Encoding.GetEncoding("iso-8859-1").GetString(data, 0, data.Length);
            return System.Uri.EscapeDataString(str).ToLower();
        }

        private static string ToMD5String(this IEnumerable<char> s)
        {
            return new string(s.ToArray()).ToMD5String();
        }

        private static string ToMD5String(this string s)
        {
            return EncryptionHelper.ComputeMd5(s);
            //return string.Join(string.Empty, MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(s)).Select(item => item.ToString("x2")).ToArray());
        }


        private static void GetLanguageAndLocale(this CultureInfo self, out string language, out string locale)
        {
            var name = self.Name;
            var n1 = name.IndexOf('-');
            if (n1 > 0)
            {
                var n2 = name.LastIndexOf('-');
                language = name.Substring(0, n1);
                locale = name.Substring(n2 + 1);
            }
            else
            {
                language = name;
                switch (language)
                {
                    case "cs":
                        locale = "CZ";
                        return;

                    case "da":
                        locale = "DK";
                        return;

                    case "el":
                        locale = "GR";
                        return;

                    case "ja":
                        locale = "JP";
                        return;

                    case "ko":
                        locale = "KR";
                        return;

                    case "sv":
                        locale = "SE";
                        return;

                    case "sr":
                        locale = "RS";
                        return;
                }
                locale = language.ToUpper();
            }
        }

        private static string GetJsonValue(this string s, string parameter)
        {
            Match match;
            return (match = Regex.Match(s, string.Format("\"?{0}\"?:\"(?<Value>.+?)\"", parameter), RegexOptions.Singleline | RegexOptions.IgnoreCase)).Success ? match.Groups["Value"].Value : null;
        }
    }
}
